home *** CD-ROM | disk | FTP | other *** search
- //***************************************************************************
- //
- // this file is (c) '94-'96 Niklas Beisert
- //
- // this file is part of the cubic player development kit.
- // you may only use/modify/spread this file under the terms stated
- // in the cubic player development kit accompanying documentation.
- //
- //***************************************************************************
-
- //[filetype 0]
- // color=1
- // name=MOD
- // interface=_plCubicPlayer
- // pllink=playxm
- // player=_xmpPlayer
- //[filetype 10]
- // color=3
- // name=XM
- // interface=_plCubicPlayer
- // pllink=playxm
- // player=_xmpPlayer
-
-
- // wavetable device example
-
- // future enhancements
- // channel mapper
-
- #include <string.h>
- #include "mcp.h"
- #include "binfile.h"
- #include "gmdinst.h"
- #include "xmplay.h"
- #include "err.h"
-
- struct channel
- {
- int chVol;
- int chFinalVol;
- int chPan;
- int chFinalPan;
- long chPitch;
- long chFinalPitch;
-
- unsigned char chCurIns;
- int chCurNormNote;
- unsigned char chSustain;
- unsigned short chFadeVol;
- unsigned short chAVibPos;
- unsigned long chAVibSwpPos;
- unsigned long chVolEnvPos;
- unsigned long chPanEnvPos;
-
- unsigned char chDefVol;
- int chDefPan;
- unsigned char chCommand;
- unsigned char chVCommand;
- long chPortaToPitch;
- long chPortaToVal;
- unsigned char chVolSlideVal;
- unsigned char chGVolSlideVal;
- unsigned char chVVolPanSlideVal;
- unsigned char chPanSlideVal;
- unsigned char chFineVolSlideUVal;
- unsigned char chFineVolSlideDVal;
- long chPortaUVal;
- long chPortaDVal;
- unsigned char chFinePortaUVal;
- unsigned char chFinePortaDVal;
- unsigned char chXFinePortaUVal;
- unsigned char chXFinePortaDVal;
- unsigned char chVibRate;
- unsigned char chVibPos;
- unsigned char chVibType;
- unsigned char chVibDep;
- unsigned char chTremRate;
- unsigned char chTremPos;
- unsigned char chTremType;
- unsigned char chTremDep;
- unsigned char chPatLoopCount;
- unsigned char chPatLoopStart;
- unsigned char chArpPos;
- unsigned char chArpNotes[3];
- unsigned char chActionTick;
- unsigned char chMRetrigPos;
- unsigned char chMRetrigLen;
- unsigned char chMRetrigAct;
- unsigned char chDelayNote;
- unsigned char chOffset;
- unsigned char chGlissando;
- unsigned char chTremorPos;
- unsigned char chTremorLen;
- unsigned char chTremorOff;
-
- int nextstop;
- int nextsamp;
- int nextpos;
- sample *cursamp;
- };
-
- static int looping;
- static int looped;
- static int usersetpos;
- static channel channels[32];
-
- static unsigned char mutech[32];
- static unsigned char globalvol;
-
- static unsigned char curtick;
- static unsigned char curtempo;
- static unsigned char tick0;
-
- static int currow;
- static unsigned char (*patptr)[5];
- static int patlen;
- static int curord;
-
- static int nord;
- static int ninst;
- static int nsamp;
- static int linearfreq;
- static int nchan;
- static int loopord;
- static int nenv;
- static instrument *instruments;
- static sample *samples;
- static envelope *envelopes;
- static unsigned char (**patterns)[5];
- static unsigned short *orders;
- static unsigned short *patlens;
-
- static int jumptoord;
- static int jumptorow;
- static int patdelay;
-
- static unsigned char procnot;
- static unsigned char procins;
- static unsigned char procvol;
- static unsigned char proccmd;
- static unsigned char procdat;
- static unsigned char notedelayed;
- static int firstspeed;
-
-
- static short sintab[256]=
- {
- 0, 50, 100, 151, 201, 251, 301, 350,
- 400, 449, 498, 546, 595, 642, 690, 737,
- 784, 830, 876, 921, 965, 1009, 1053, 1096,
- 1138, 1179, 1220, 1260, 1299, 1338, 1375, 1412,
- 1448, 1483, 1517, 1551, 1583, 1615, 1645, 1674,
- 1703, 1730, 1757, 1782, 1806, 1829, 1851, 1872,
- 1892, 1911, 1928, 1945, 1960, 1974, 1987, 1998,
- 2009, 2018, 2026, 2033, 2038, 2042, 2046, 2047,
- 2048, 2047, 2046, 2042, 2038, 2033, 2026, 2018,
- 2009, 1998, 1987, 1974, 1960, 1945, 1928, 1911,
- 1892, 1872, 1851, 1829, 1806, 1782, 1757, 1730,
- 1703, 1674, 1645, 1615, 1583, 1551, 1517, 1483,
- 1448, 1412, 1375, 1338, 1299, 1260, 1220, 1179,
- 1138, 1096, 1053, 1009, 965, 921, 876, 830,
- 784, 737, 690, 642, 595, 546, 498, 449,
- 400, 350, 301, 251, 201, 151, 100, 50,
- 0, -50, -100, -151, -201, -251, -301, -350,
- -400, -449, -498, -546, -595, -642, -690, -737,
- -784, -830, -876, -921, -965, -1009, -1053, -1096,
- -1138, -1179, -1220, -1260, -1299, -1338, -1375, -1412,
- -1448, -1483, -1517, -1551, -1583, -1615, -1645, -1674,
- -1703, -1730, -1757, -1782, -1806, -1829, -1851, -1872,
- -1892, -1911, -1928, -1945, -1960, -1974, -1987, -1998,
- -2009, -2018, -2026, -2033, -2038, -2042, -2046, -2047,
- -2048, -2047, -2046, -2042, -2038, -2033, -2026, -2018,
- -2009, -1998, -1987, -1974, -1960, -1945, -1928, -1911,
- -1892, -1872, -1851, -1829, -1806, -1782, -1757, -1730,
- -1703, -1674, -1645, -1615, -1583, -1551, -1517, -1483,
- -1448, -1412, -1375, -1338, -1299, -1260, -1220, -1179,
- -1138, -1096, -1053, -1009, -965, -921, -876, -830,
- -784, -737, -690, -642, -595, -546, -498, -449,
- -400, -350, -301, -251, -201, -151, -100, -50
- };
-
- static int freqrange(int x)
- {
- if (linearfreq)
- return (x<-72*256)?-72*256:(x>96*256)?96*256:x;
- else
- return (x<107)?107:(x>438272)?438272:x;
- }
-
- static int volrange(int x)
- {
- return (x<0)?0:(x>0x40)?0x40:x;
- }
-
- static int panrange(int x)
- {
- return (x<0)?0:(x>0xFF)?0xFF:x;
- }
-
-
- static void PlayNote(channel &ch)
- {
- int portatmp=0;
-
- if (procins>ninst)
- procins=0;
-
- if (proccmd==3)
- portatmp=1;
- if (proccmd==5)
- portatmp=1;
- if (procvol>=0xF0)
- portatmp=1;
-
- int keyoff=0;
- if (procnot==97)
- {
- procnot=0;
- keyoff=1;
- }
- if ((proccmd==20)&&!procdat)
- keyoff=1;
-
- if (procins&&(procins<=ninst))
- ch.chCurIns=procins;
-
- if (!ch.chCurIns)
- return;
-
- if (procnot)
- {
- if (procins!=0)
- ch.chSustain=1;
-
- ch.chDelayNote=procnot;
- if (proccmd==49)
- {
- if (procdat!=0)
- return;
- }
-
- procnot--;
- if (!portatmp)
- {
- ch.nextstop=1;
-
- instrument &ins=instruments[ch.chCurIns-1];
- if (instruments[ch.chCurIns-1].samples[procnot]>nsamp)
- return;
- ch.cursamp=&samples[instruments[ch.chCurIns-1].samples[procnot]];
-
- ch.nextsamp=ch.cursamp->handle;
-
- if (procins)
- {
- ch.chDefVol=(ch.cursamp->stdvol+1)>>2;
- ch.chDefPan=ch.cursamp->stdpan;
- }
-
- ch.chCurNormNote=ch.cursamp->normnote;
-
- int frq=48*256-((procnot<<8)-ch.chCurNormNote);
- if (!linearfreq)
- frq=mcpGetFreq6848(frq);
- ch.chPitch=frq;
- ch.chFinalPitch=frq;
- ch.chPortaToPitch=frq;
-
- ch.nextpos=0;
-
- if (proccmd==9)
- {
- if (procdat!=0)
- ch.chOffset=procdat;
- ch.nextpos=ch.chOffset<<8;
- }
-
- ch.chVibPos=0;
- ch.chTremPos=0;
- ch.chArpPos=0;
- ch.chMRetrigPos=0;
- ch.chTremorPos=0;
- }
- else
- {
- int frq=48*256-((procnot<<8)-ch.chCurNormNote);
- if (!linearfreq)
- frq=mcpGetFreq6848(frq);
- ch.chPortaToPitch=frq;
- }
- }
-
- if (keyoff&&ch.cursamp)
- {
- ch.chSustain=0;
- if ((ch.cursamp->volenv>=nenv)&&!procins)
- ch.chFadeVol=0;
- }
-
- if (!ch.chSustain)
- return;
- if (!procins)
- return;
-
- if (!notedelayed)
- {
- ch.chVol=ch.chDefVol;
- ch.chFinalVol=ch.chDefVol;
- if (ch.chDefPan!=-1)
- {
- ch.chPan=ch.chDefPan;
- ch.chFinalPan=ch.chDefPan;
- }
- }
- ch.chFadeVol=0x8000;
- ch.chAVibPos=0;
- ch.chAVibSwpPos=0;
- ch.chVolEnvPos=0;
- ch.chPanEnvPos=0;
- }
-
- static unsigned short notetab[16]={32768,30929,29193,27554,26008,24548,23170,21870,20643,19484,18390,17358,16384,15464,14596,13777};
-
- static void xmpPlayTick()
- {
- if (firstspeed)
- {
- mcpSet(-1, mcpGSpeed, firstspeed);
- firstspeed=0;
- }
-
- tick0=0;
- int i;
- for (i=0; i<nchan; i++)
- {
- channel &ch=channels[i];
- ch.chFinalVol=ch.chVol;
- ch.chFinalPan=ch.chPan;
- ch.chFinalPitch=ch.chPitch;
- ch.nextstop=0;
- ch.nextsamp=-1;
- ch.nextpos=-1;
- }
-
- curtick++;
- if (curtick>=curtempo)
- curtick=0;
-
- if (!curtick&&patdelay)
- {
- if (jumptoord!=-1)
- {
- if (jumptoord!=curord)
- for (i=0; i<nchan; i++)
- {
- channel &ch=channels[i];
- ch.chPatLoopCount=0;
- ch.chPatLoopStart=0;
- }
-
- if (jumptoord>=nord)
- jumptoord=loopord;
- if ((jumptoord<curord)&&!usersetpos)
- looped=1;
- usersetpos=0;
-
- curord=jumptoord;
- currow=jumptorow;
- jumptoord=-1;
- patlen=patlens[orders[curord]];
- patptr=patterns[orders[curord]];
- }
- }
-
- if (!curtick&&patdelay)
- {
- patdelay--;
- }
- else
- if (!curtick)
- {
- tick0=1;
-
- currow++;
- if ((jumptoord==-1)&&(currow>=patlen))
- {
- jumptoord=curord+1;
- jumptorow=0;
- }
- if (jumptoord!=-1)
- {
- if (jumptoord!=curord)
- for (i=0; i<nchan; i++)
- {
- channel &ch=channels[i];
- ch.chPatLoopCount=0;
- ch.chPatLoopStart=0;
- }
-
- if (jumptoord>=nord)
- jumptoord=loopord;
- if ((jumptoord<curord)&&!usersetpos)
- looped=1;
- usersetpos=0;
-
- curord=jumptoord;
- currow=jumptorow;
- jumptoord=-1;
- patlen=patlens[orders[curord]];
- patptr=patterns[orders[curord]];
- }
-
-
- for (i=0; i<nchan; i++)
- {
- channel &ch=channels[i];
- procnot=patptr[nchan*currow+i][0];
- procins=patptr[nchan*currow+i][1];
- procvol=patptr[nchan*currow+i][2];
- proccmd=patptr[nchan*currow+i][3];
- procdat=patptr[nchan*currow+i][4];
-
- notedelayed=0;
- PlayNote(ch);
-
- ch.chVCommand=procvol>>4;
- procvol&=0xF;
- switch (ch.chVCommand)
- {
- case 1: case 2: case 3: case 4:
- ch.chFinalVol=ch.chVol=procvol+ch.chVCommand*0x10-0x10;
- break;
- case 5:
- ch.chFinalVol=ch.chVol=0x40;
- break;
- case 6: case 7: case 13: case 14:
- ch.chVVolPanSlideVal=procvol;
- break;
- case 8:
- ch.chVol-=procvol;
- ch.chFinalVol=ch.chVol=volrange(ch.chVol);
- break;
- case 9:
- ch.chVol+=procvol;
- ch.chFinalVol=ch.chVol=volrange(ch.chVol);
- break;
- case 10:
- if (procvol)
- ch.chVibRate=(procvol<<2);
- break;
- case 11:
- if (procvol)
- ch.chVibDep=(procvol<<2);
- break;
- case 12:
- ch.chFinalPan=ch.chPan=procvol*0x11;
- break;
- case 15:
- if (procvol)
- ch.chPortaToVal=procvol<<8;
- break;
- }
-
- ch.chCommand=proccmd;
- switch (ch.chCommand)
- {
- case 0:
- if (procdat)
- ch.chCommand=0xFF;
- ch.chArpNotes[0]=0;
- ch.chArpNotes[1]=procdat>>4;
- ch.chArpNotes[2]=procdat&0xF;
- break;
- case 1:
- if (procdat)
- ch.chPortaUVal=procdat<<4;
- break;
- case 2:
- if (procdat)
- ch.chPortaDVal=procdat<<4;
- break;
- case 3:
- if (procdat)
- ch.chPortaToVal=procdat<<4;
- break;
- case 4:
- if (procdat&0xF)
- ch.chVibDep=(procdat&0xF)<<2;
- if (procdat&0xF0)
- ch.chVibRate=(procdat>>4)<<2;
- break;
- case 5: case 6: case 10:
- if (procdat)
- ch.chVolSlideVal=procdat;
- break;
- case 7:
- if (procdat&0xF)
- ch.chTremDep=(procdat&0xF)<<2;
- if (procdat&0xF0)
- ch.chTremRate=(procdat>>4)<<2;
- break;
- case 8:
- ch.chFinalPan=ch.chPan=procdat;
- break;
- case 11:
- jumptoord=procdat;
- jumptorow=0;
- break;
- case 12:
- ch.chFinalVol=ch.chVol=volrange(procdat);
- break;
- case 13:
- if (jumptoord==-1)
- jumptoord=curord+1;
- jumptorow=(procdat&0xF)+(procdat>>4)*10;
- break;
- case 15:
- if (!procdat)
- {
- jumptoord=procdat;
- jumptorow=0;
- break;
- }
- if (procdat>=0x20)
- mcpSet(-1, mcpGSpeed, 256*2*procdat/5);
- else
- curtempo=procdat;
- break;
- case 16:
- globalvol=volrange(procdat);
- break;
- case 17:
- if (procdat)
- ch.chGVolSlideVal=procdat;
- break;
- case 20: case 45: case 48: case 49:
- ch.chActionTick=procdat;
- break;
- case 21:
- ch.chVolEnvPos=ch.chPanEnvPos=procdat;
- if (ch.cursamp->volenv<nenv)
- if (ch.chVolEnvPos>envelopes[ch.cursamp->volenv].len)
- ch.chVolEnvPos=envelopes[ch.cursamp->volenv].len;
- if (ch.cursamp->panenv<nenv)
- if (ch.chPanEnvPos>envelopes[ch.cursamp->panenv].len)
- ch.chPanEnvPos=envelopes[ch.cursamp->panenv].len;
- break;
- case 25:
- if (procdat)
- ch.chPanSlideVal=procdat;
- break;
- case 27:
- if (procdat)
- {
- ch.chMRetrigLen=procdat&0xF;
- ch.chMRetrigAct=procdat>>4;
- ch.chMRetrigPos=0;
- }
- break;
- case 29:
- if (procdat)
- {
- ch.chTremorLen=(procdat&0xF)+(procdat>>4)+2;
- ch.chTremorOff=(procdat>>4)+1;
- ch.chTremorPos=0;
- }
- break;
- case 33:
- if ((procdat>>4)==1)
- {
- if (procdat&0xF)
- ch.chXFinePortaUVal=procdat&0xF;
- ch.chFinalPitch=ch.chPitch=freqrange(ch.chPitch-(ch.chXFinePortaUVal<<2));
- }
- else
- if ((procdat>>4)==2)
- {
- if (procdat&0xF)
- ch.chXFinePortaDVal=procdat&0xF;
- ch.chFinalPitch=ch.chPitch=freqrange(ch.chPitch+(ch.chXFinePortaDVal<<2));
- }
- break;
- case 37:
- if (procdat)
- ch.chFinePortaUVal=procdat;
- ch.chFinalPitch=ch.chPitch=freqrange(ch.chPitch-(ch.chFinePortaUVal<<4));
- break;
- case 38:
- if (procdat)
- ch.chFinePortaDVal=procdat;
- ch.chFinalPitch=ch.chPitch=freqrange(ch.chPitch-(ch.chFinePortaDVal<<4));
- break;
- case 39:
- ch.chGlissando=procdat;
- break;
- case 40:
- ch.chVibType=procdat&3;
- break;
- case 42:
- if (procdat)
- ch.chPatLoopStart=currow;
- else
- {
- ch.chPatLoopCount++;
- if (ch.chPatLoopCount<=procdat)
- {
- jumptorow=ch.chPatLoopStart;
- jumptoord=curord;
- }
- else
- {
- ch.chPatLoopCount=0;
- ch.chPatLoopStart=currow+1;
- }
- }
- break;
- case 43:
- ch.chTremType=procdat&3;
- break;
- case 44:
- ch.chFinalPan=ch.chPan=procdat*0x11;
- break;
- case 46:
- if (procdat)
- ch.chFineVolSlideUVal=procdat;
- ch.chFinalVol=ch.chVol=volrange(ch.chVol+ch.chFineVolSlideUVal);
- break;
- case 47:
- if (procdat)
- ch.chFineVolSlideDVal=procdat;
- ch.chFinalVol=ch.chVol=volrange(ch.chVol-ch.chFineVolSlideDVal);
- break;
- case 50:
- patdelay=procdat;
- break;
- }
- }
- }
-
- for (i=0; i<nchan; i++)
- {
- channel &ch=channels[i];
-
- switch (ch.chVCommand)
- {
- case 6:
- if (tick0)
- break;
- ch.chFinalVol=ch.chVol=volrange(ch.chVol-ch.chVVolPanSlideVal);
- break;
- case 7:
- if (tick0)
- break;
- ch.chFinalVol=ch.chVol=volrange(ch.chVol+ch.chVVolPanSlideVal);
- break;
- case 11:
- switch (ch.chVibType)
- {
- case 0:
- ch.chFinalPitch=freqrange((( sintab[ch.chVibPos] *ch.chVibDep)>>8)+ch.chFinalPitch);
- break;
- case 1:
- ch.chFinalPitch=freqrange((( (ch.chVibPos-0x80) *ch.chVibDep)>>4)+ch.chFinalPitch);
- break;
- case 2:
- ch.chFinalPitch=freqrange((( ((ch.chVibPos&0x80)-0x40) *ch.chVibDep)>>3)+ch.chFinalPitch);
- break;
- }
- if (!tick0)
- ch.chVibPos+=ch.chVibRate;
- break;
- case 13:
- if (tick0)
- break;
- ch.chFinalPan=ch.chPan=panrange(ch.chPan-ch.chVVolPanSlideVal);
- break;
- case 14:
- if (tick0)
- break;
- ch.chFinalPan=ch.chPan=panrange(ch.chPan+ch.chVVolPanSlideVal);
- break;
- case 15:
- if (!tick0)
- if (ch.chPitch<ch.chPortaToPitch)
- {
- ch.chPitch+=ch.chPortaToVal;
- if (ch.chPitch>ch.chPortaToPitch)
- ch.chPitch=ch.chPortaToPitch;
- }
- else
- {
- ch.chPitch-=ch.chPortaToVal;
- if (ch.chPitch<ch.chPortaToPitch)
- ch.chPitch=ch.chPortaToPitch;
- }
- if (ch.chGlissando)
- {
- if (linearfreq)
- ch.chFinalPitch=((ch.chPitch+ch.chCurNormNote+0x80)&~0xFF)-ch.chCurNormNote;
- else
- ch.chFinalPitch=mcpGetFreq6848(((mcpGetNote6848(ch.chPitch)+ch.chCurNormNote+0x80)&~0xFF)-ch.chCurNormNote);
- }
- else
- ch.chFinalPitch=ch.chPitch;
- break;
- }
-
- switch (ch.chCommand)
- {
- case 0:
- if (linearfreq)
- ch.chFinalPitch=freqrange(ch.chFinalPitch-(ch.chArpNotes[ch.chArpPos]<<8));
- else
- ch.chFinalPitch=freqrange((ch.chFinalPitch*notetab[ch.chArpNotes[ch.chArpPos]])>>15);
- ch.chArpPos++;
- if (ch.chArpPos==3)
- ch.chArpPos=0;
- break;
- case 1:
- if (tick0)
- break;
- ch.chFinalPitch=ch.chPitch=freqrange(ch.chPitch-ch.chPortaUVal);
- break;
- case 2:
- if (tick0)
- break;
- ch.chFinalPitch=ch.chPitch=freqrange(ch.chPitch+ch.chPortaDVal);
- break;
- case 3:
- if (!tick0)
- if (ch.chPitch<ch.chPortaToPitch)
- {
- ch.chPitch+=ch.chPortaToVal;
- if (ch.chPitch>ch.chPortaToPitch)
- ch.chPitch=ch.chPortaToPitch;
- }
- else
- {
- ch.chPitch-=ch.chPortaToVal;
- if (ch.chPitch<ch.chPortaToPitch)
- ch.chPitch=ch.chPortaToPitch;
- }
- if (ch.chGlissando)
- {
- if (linearfreq)
- ch.chFinalPitch=((ch.chPitch+ch.chCurNormNote+0x80)&~0xFF)-ch.chCurNormNote;
- else
- ch.chFinalPitch=mcpGetFreq6848(((mcpGetNote6848(ch.chPitch)+ch.chCurNormNote+0x80)&~0xFF)-ch.chCurNormNote);
- }
- else
- ch.chFinalPitch=ch.chPitch;
- break;
- case 4:
- switch (ch.chVibType)
- {
- case 0:
- ch.chFinalPitch=freqrange((( sintab[ch.chVibPos] *ch.chVibDep)>>8)+ch.chFinalPitch);
- break;
- case 1:
- ch.chFinalPitch=freqrange((( (ch.chVibPos-0x80) *ch.chVibDep)>>4)+ch.chFinalPitch);
- break;
- case 2:
- ch.chFinalPitch=freqrange((( ((ch.chVibPos&0x80)-0x40) *ch.chVibDep)>>3)+ch.chFinalPitch);
- break;
- }
- if (!tick0)
- ch.chVibPos+=ch.chVibRate;
- break;
- case 5:
- if (!tick0)
- if (ch.chPitch<ch.chPortaToPitch)
- {
- ch.chPitch+=ch.chPortaToVal;
- if (ch.chPitch>ch.chPortaToPitch)
- ch.chPitch=ch.chPortaToPitch;
- }
- else
- {
- ch.chPitch-=ch.chPortaToVal;
- if (ch.chPitch<ch.chPortaToPitch)
- ch.chPitch=ch.chPortaToPitch;
- }
- if (ch.chGlissando)
- {
- if (linearfreq)
- ch.chFinalPitch=((ch.chPitch+ch.chCurNormNote+0x80)&~0xFF)-ch.chCurNormNote;
- else
- ch.chFinalPitch=mcpGetFreq6848(((mcpGetNote6848(ch.chPitch)+ch.chCurNormNote+0x80)&~0xFF)-ch.chCurNormNote);
- }
- else
- ch.chFinalPitch=ch.chPitch;
-
- if (tick0)
- break;
- ch.chFinalVol=ch.chVol=volrange(ch.chVol+((ch.chVolSlideVal&0xF0)?(ch.chVolSlideVal>>4):-(ch.chVolSlideVal&0xF)));
- break;
- case 6:
- switch (ch.chVibType)
- {
- case 0:
- ch.chFinalPitch=freqrange((( sintab[ch.chVibPos] *ch.chVibDep)>>8)+ch.chFinalPitch);
- break;
- case 1:
- ch.chFinalPitch=freqrange((( (ch.chVibPos-0x80) *ch.chVibDep)>>4)+ch.chFinalPitch);
- break;
- case 2:
- ch.chFinalPitch=freqrange((( ((ch.chVibPos&0x80)-0x40) *ch.chVibDep)>>3)+ch.chFinalPitch);
- break;
- }
- if (!tick0)
- ch.chVibPos+=ch.chVibRate;
-
- if (tick0)
- break;
- ch.chFinalVol=ch.chVol=volrange(ch.chVol+((ch.chVolSlideVal&0xF0)?(ch.chVolSlideVal>>4):-(ch.chVolSlideVal&0xF)));
- break;
- case 7:
- switch (ch.chTremType)
- {
- case 0:
- ch.chFinalVol+=(( sintab[ch.chTremPos] *ch.chTremDep)>>11);
- break;
- case 1:
- ch.chFinalVol+=(( (ch.chTremPos-0x80) *ch.chTremDep)>>7);
- break;
- case 2:
- ch.chFinalVol+=(( ((ch.chTremPos&0x80)-0x40) *ch.chTremDep)>>6);
- break;
- }
- ch.chFinalVol=volrange(ch.chFinalVol);
- if (!tick0)
- ch.chTremPos+=ch.chTremRate;
- break;
- case 10:
- if (tick0)
- break;
- ch.chFinalVol=ch.chVol=volrange(ch.chVol+((ch.chVolSlideVal&0xF0)?(ch.chVolSlideVal>>4):-(ch.chVolSlideVal&0xF)));
- break;
- case 17:
- if (tick0)
- break;
- if (ch.chGVolSlideVal&0xF0)
- globalvol=volrange(globalvol+(ch.chGVolSlideVal>>4));
- else
- globalvol=volrange(globalvol-(ch.chGVolSlideVal&0xF));
- break;
- case 20:
- if (tick0)
- break;
- if (curtick==ch.chActionTick)
- {
- ch.chSustain=0;
- if (ch.cursamp&&(ch.cursamp->volenv>=nenv))
- ch.chFadeVol=0;
- }
- break;
- case 25:
- if (tick0)
- break;
- ch.chFinalPan=ch.chPan=panrange(ch.chPan+((ch.chPanSlideVal&0xF0)?(ch.chPanSlideVal>>4):-(ch.chPanSlideVal&0xF)));
- break;
- case 27:
- if (ch.chMRetrigPos++!=ch.chMRetrigLen)
- break;
- ch.chMRetrigPos=0;
- ch.nextpos=0;
-
- switch (ch.chMRetrigAct)
- {
- case 0: case 8: break;
- case 1: case 2: case 3: case 4: case 5:
- ch.chVol=ch.chVol-(1<<(ch.chMRetrigAct-1));
- break;
- case 9: case 10: case 11: case 12: case 13:
- ch.chVol=ch.chVol+(1<<(ch.chMRetrigAct-9));
- break;
- case 6: ch.chVol=(ch.chVol*5)>>3; break;
- case 14: ch.chVol=(ch.chVol*3)>>1; break;
- case 7: ch.chVol>>=1; break;
- case 15: ch.chVol<<=1; break;
- }
- ch.chFinalVol=ch.chVol=volrange(ch.chVol);
- break;
- case 29:
- if (ch.chTremorPos>=ch.chTremorOff)
- ch.chFinalVol=0;
- if (tick0)
- break;
- ch.chTremorPos++;
- if (ch.chTremorPos==ch.chTremorLen)
- ch.chTremorPos=0;
- break;
- case 45:
- if (!ch.chActionTick)
- break;
- if (!(curtick%ch.chActionTick))
- ch.nextpos=0;
- break;
- case 48:
- if (tick0)
- break;
- if (curtick==ch.chActionTick)
- ch.chFinalVol=ch.chVol=0;
- break;
- case 49:
- if (tick0)
- break;
- if (curtick!=ch.chActionTick)
- break;
- notedelayed=1;
- procnot=ch.chDelayNote;
- procins=ch.chCurIns;
- proccmd=0;
- procdat=0;
- procvol=0;
- PlayNote(ch);
- break;
- }
-
- if (!ch.cursamp)
- {
- mcpSet(i, mcpCStatus, 0);
- continue;
- }
- sample &sm=*ch.cursamp;
-
- int vol=(ch.chFinalVol*globalvol)>>4;
- int pan=ch.chFinalPan-128;
- if (!ch.chSustain)
- {
- vol=(vol*ch.chFadeVol)>>15;
- if (ch.chFadeVol>=sm.volfade)
- ch.chFadeVol-=sm.volfade;
- else
- ch.chFadeVol=0;
- }
-
- if (sm.volenv<nenv)
- {
- const envelope &env=envelopes[sm.volenv];
- vol=(env.env[ch.chVolEnvPos]*vol)>>8;
-
- if (ch.chVolEnvPos<env.len)
- ch.chVolEnvPos++;
- if (ch.chSustain&&(env.type&mpEnvSLoop))
- {
- if (ch.chVolEnvPos==env.sloope)
- ch.chVolEnvPos=env.sloops;
- }
- else
- if (env.type&mpEnvLoop)
- {
- if (ch.chVolEnvPos==env.loope)
- ch.chVolEnvPos=env.loops;
- }
- }
-
- if (sm.panenv<nenv)
- {
- const envelope &env=envelopes[sm.panenv];
- pan+=((env.env[ch.chPanEnvPos]-128)*(128-((pan<0)?-pan:pan)))>>7;
-
- if (ch.chPanEnvPos<env.len)
- ch.chPanEnvPos++;
- if (ch.chSustain&&(env.type&mpEnvSLoop))
- {
- if (ch.chPanEnvPos==env.sloope)
- ch.chPanEnvPos=env.sloops;
- }
- else
- if (env.type&mpEnvLoop)
- {
- if (ch.chPanEnvPos==env.loope)
- ch.chPanEnvPos=env.loops;
- }
- }
-
- if (sm.vibrate&&sm.vibdepth)
- {
- int dep=0;
- switch (sm.vibtype)
- {
- case 0:
- dep=(sintab[(ch.chAVibPos>>8)&0xFF]*sm.vibdepth)>>11;
- break;
- case 1:
- dep=(ch.chAVibPos&0x8000)?-sm.vibdepth:sm.vibdepth;
- break;
- case 2:
- dep=(sm.vibdepth*(32768-ch.chAVibPos))>>14;
- break;
- case 3:
- dep=(sm.vibdepth*(ch.chAVibPos-32768))>>14;
- break;
- }
-
- ch.chAVibSwpPos+=sm.vibsweep;
- if (ch.chAVibSwpPos>0x10000)
- ch.chAVibSwpPos=0x10000;
- dep=(dep*(int)ch.chAVibSwpPos)>>16;
-
- ch.chFinalPitch-=dep;
-
- ch.chAVibPos+=sm.vibrate;
- }
-
- if (ch.nextstop)
- mcpSet(i, mcpCStatus, 0);
- if (ch.nextsamp!=-1)
- mcpSet(i, mcpCInstrument, ch.nextsamp);
- if (ch.nextpos!=-1)
- {
- mcpSet(i, mcpCPosition, ch.nextpos);
- mcpSet(i, mcpCStatus, 1);
- }
- if (linearfreq)
- mcpSet(i, mcpCPitch, -ch.chFinalPitch);
- else
- mcpSet(i, mcpCPitch6848, ch.chFinalPitch);
- mcpSet(i, mcpCVolume, (looping||!looped)?vol:0);
- mcpSet(i, mcpCPanning, pan);
- mcpSet(i, mcpCMute, mutech[i]);
- }
- }
-
-
-
- int xmpChanActive(int ch)
- {
- return mcpGet(ch, mcpCStatus)&&channels[ch].cursamp&&channels[ch].chVol&&channels[ch].chFadeVol;
- }
-
- int xmpGetChanIns(int ch)
- {
- return channels[ch].chCurIns;
- }
-
- int xmpGetChanSamp(int ch)
- {
- if (!channels[ch].cursamp)
- return 0xFFFF;
- return channels[ch].cursamp-samples;
- }
-
- int xmpGetDotsData(int ch, int &smp, int &frq, int &voll, int &volr, int &sus)
- {
- if (!mcpGet(ch, mcpCStatus))
- return 0;
- channel &c=channels[ch];
- if (!c.cursamp||!c.chVol||!c.chFadeVol)
- return 0;
- smp=c.cursamp-samples;
- if (linearfreq)
- frq=60*256+c.cursamp->normnote-freqrange(c.chFinalPitch);
- else
- frq=60*256+c.cursamp->normnote+mcpGetNote8363(6848*8363/freqrange(c.chFinalPitch));
- mcpGetRealVolume(ch, voll, volr);
- sus=c.chSustain;
- return 1;
- }
-
- void xmpGetRealVolume(int ch, int &voll, int &volr)
- {
- mcpGetRealVolume(ch, voll, volr);
- }
-
- unsigned short xmpGetPos()
- {
- return (curord<<8)|currow;
- }
-
- void xmpSetPos(int ord, int row)
- {
- if (row<0)
- ord--;
- if (ord>=nord)
- ord=0;
- if (ord<0)
- {
- ord=0;
- row=0;
- }
- if (row>=patlens[orders[ord]])
- {
- ord++;
- row=0;
- }
- if (ord>=nord)
- ord=0;
- if (row<0)
- {
- row+=patlens[orders[ord]];
- if (row<0)
- row=0;
- }
- int i;
- for (i=0; i<nchan; i++)
- mcpSet(i, mcpCReset, 0);
- jumptoord=ord;
- jumptorow=row;
- curtick=curtempo;
- curord=ord;
- currow=row;
- usersetpos=1;
- }
-
- int xmpGetLChanSample(int ch, short *b, int len, int rate)
- {
- return mcpGetChanSample(ch, b, len, rate);
- }
-
- void xmpMute(int i, int m)
- {
- mutech[i]=m;
- }
-
- int xmpLoop()
- {
- return looped;
- }
-
- void xmpSetLoop(int x)
- {
- looping=x;
- }
-
- int xmpPlayModule(xmodule &m)
- {
- int i;
- mcpLoadSamples(m.sampleinfos, m.nsampi);
-
- memset(channels, 0, sizeof(channels));
-
- globalvol=0x40;
- jumptorow=0;
- jumptoord=0;
- curord=0;
- currow=0;
- ninst=m.ninst;
- nord=m.nord;
- nsamp=m.nsamp;
- instruments=m.instruments;
- envelopes=m.envelopes;
- samples=m.samples;
- patterns=m.patterns;
- orders=m.orders;
- patlens=m.patlens;
- linearfreq=m.linearfreq;
- nchan=m.nchan;
- loopord=m.loopord;
- nenv=m.nenv;
- looped=0;
-
- curtempo=m.initempo;
- curtick=m.initempo-1;
-
- for (i=0; i<nchan; i++)
- {
- channels[i].chPan=((i*3)&2)?0xFF:0x00;
- mutech[i]=0;
- }
-
- firstspeed=256*2*m.inibpm/5;
- if (!mcpOpenPlayer(nchan, xmpPlayTick))
- return 0;
-
- if (nchan!=mcpNChan)
- {
- mcpClosePlayer();
- return 0;
- }
-
- return 1;
- }
-
- void xmpStopModule()
- {
- mcpClosePlayer();
- }
-
- int xmpLoadModule(xmodule &m, binfile &file)
- {
- m.envelopes=0;
- m.samples=0;
- m.instruments=0;
- m.sampleinfos=0;
- m.patlens=0;
- m.patterns=0;
- m.orders=0;
-
- struct
- {
- char sig[17];
- char name[20];
- char eof;
- char tracker[20];
- unsigned short ver;
- unsigned long hdrsize;
- } head1;
-
- struct
- {
- unsigned short nord;
- unsigned short loopord;
- unsigned short nchan;
- unsigned short npat;
- unsigned short ninst;
- unsigned short freqtab;
- unsigned short tempo;
- unsigned short bpm;
- unsigned char ord[256];
- } head2;
-
- file.read(&head1, sizeof(head1));
- if (memcmp(head1.sig, "Extended Module: ", 17))
- return errFormStruc;
- if (head1.eof!=26)
- return errFormStruc;
- if (head1.ver<0x104)
- return errFormOldVer;
- file.read(&head2, sizeof(head2));
- file.seekcur(head1.hdrsize-4-sizeof(head2));
-
- if (!head2.ninst)
- return errFormMiss;
-
- memcpy(m.name, head1.name, 20);
- m.name[20]=0;
-
- m.linearfreq=!!(head2.freqtab&1);
- m.nchan=head2.nchan;
- m.ninst=head2.ninst;
- m.nenv=head2.ninst*2;
- m.npat=head2.npat+1;
- m.nord=head2.nord;
- m.loopord=head2.loopord;
- m.inibpm=head2.bpm;
- m.initempo=head2.tempo;
-
- m.orders=new unsigned short [head2.nord];
- m.patterns=(unsigned char (**)[5])new void *[head2.npat+1];
- m.patlens=new unsigned short [head2.npat+1];
- m.instruments=new instrument [head2.ninst];
- m.envelopes=new envelope [head2.ninst*2];
- sampleinfo **smps=new sampleinfo *[head2.ninst];
- sample **msmps=new sample *[head2.ninst];
- int *instsmpnum=new int [head2.ninst];
-
- if (!smps||!msmps||!instsmpnum||!m.instruments||!m.envelopes||!m.patterns||!m.orders||!m.patlens)
- return errAllocMem;
-
- memset(m.patterns, 0, (head2.npat+1)*sizeof(void*));
- memset(m.envelopes, 0, (head2.ninst*2)*sizeof(envelope));
-
- int i,j,k;
-
- for (i=0; i<head2.nord; i++)
- m.orders[i]=(head2.ord[i]<head2.npat)?head2.ord[i]:head2.npat;
-
- m.patlens[head2.npat]=64;
- m.patterns[head2.npat]=new unsigned char [64*head2.nchan][5];
- if (!m.patterns[head2.npat])
- return errAllocMem;
- memset(m.patterns[head2.npat], 0, 64*5*head2.nchan);
-
- for (i=0; i<head2.npat; i++)
- {
- struct
- {
- unsigned long len;
- unsigned char ptype;
- unsigned short rows;
- unsigned short patdata;
- } pathead;
- file.read(&pathead, sizeof(pathead));
- file.seekcur(pathead.len-sizeof(pathead));
- m.patlens[i]=pathead.rows;
- m.patterns[i]=new unsigned char [pathead.rows*head2.nchan][5];
- if (!m.patterns[i])
- return errAllocMem;
- memset(m.patterns[i], 0, pathead.rows*head2.nchan*5);
- if (!pathead.patdata)
- continue;
- unsigned char *pbuf=new unsigned char [pathead.patdata];
- if (!pbuf)
- return errAllocMem;
- file.read(pbuf, pathead.patdata);
- unsigned char *pbp=pbuf;
- unsigned char *cur=(unsigned char*)(m.patterns[i]);
- for (j=0; j<(pathead.rows*head2.nchan); j++)
- {
- unsigned char pack=(*pbp&0x80)?(*pbp++):0x1F;
- for (k=0; k<5; k++)
- {
- *cur++=(pack&1)?*pbp++:0;
- pack>>=1;
- }
- if (cur[-2]==0xE)
- {
- cur[-2]=36+(cur[-1]>>4);
- cur[-1]&=0xF;
- }
- }
- delete pbuf;
- }
-
- m.nsampi=0;
- m.nsamp=0;
- for (i=0; i<m.ninst; i++)
- {
- instrument &ip=m.instruments[i];
- envelope *env=m.envelopes+2*i;
- smps[i]=0;
- msmps[i]=0;
- struct
- {
- unsigned long size;
- char name[22];
- char type;
- unsigned short samp;
- } ins1;
- file.read(&ins1, sizeof(ins1));
- memcpy(ip.name, ins1.name, 22);
- ip.name[22]=0;
- memset(ip.samples, -1, 256);
- instsmpnum[i]=ins1.samp;
- if (!ins1.samp)
- {
- file.seekcur(ins1.size-sizeof(ins1));
- continue;
- }
- struct
- {
- unsigned long shsize;
- unsigned char snum[96];
- unsigned short venv[12][2];
- unsigned short penv[12][2];
- unsigned char vnum, pnum;
- unsigned char vsustain, vloops, vloope, psustain, ploops, ploope;
- unsigned char vtype, ptype;
- unsigned char vibtype, vibsweep, vibdepth, vibrate;
- unsigned short volfade;
- unsigned short res;
- } ins2;
- file.read(&ins2, sizeof(ins2));
- file.seekcur(ins1.size-sizeof(ins1)-sizeof(ins2));
-
- smps[i]=new sampleinfo[ins1.samp];
- msmps[i]=new sample[ins1.samp];
- if (!smps[i]||!msmps[i])
- return errAllocMem;
- memset(msmps[i], 0, sizeof(**msmps)*ins1.samp);
- memset(smps[i], 0, sizeof(**smps)*ins1.samp);
-
- memset(ip.samples, 0xFF, 128*2);
- for (j=0; j<96; j++)
- if (ins2.snum[j]<ins1.samp)
- ip.samples[j]=m.nsamp+ins2.snum[j];
- unsigned short volfade=0xFFFF;
- volfade=ins2.volfade;
- if (ins2.vtype&1)
- {
- env[0].speed=0;
- env[0].type=0;
- env[0].env=new unsigned char[ins2.venv[ins2.vnum-1][0]+1];
- if (!env[0].env)
- return errAllocMem;
- short k, p=0, h=ins2.venv[0][1]*4;
- for (j=1; j<ins2.vnum; j++)
- {
- short l=ins2.venv[j][0]-p;
- short dh=ins2.venv[j][1]*4-h;
- for (k=0; k<l; k++)
- {
- short cv=h+dh*k/l;
- env[0].env[p++]=(cv>255)?255:cv;
- }
- h+=dh;
- }
- env[0].len=p;
- env[0].env[p]=(h>255)?255:h;
- if (ins2.vtype&2)
- {
- env[0].type|=mpEnvSLoop;
- if (!(ins2.vtype&4)||(ins2.vsustain<=ins2.vloope))
- {
- env[0].sloops=ins2.venv[ins2.vsustain][0];
- env[0].sloope=ins2.venv[ins2.vsustain][0]+1;
- }
- else
- {
- env[0].sloops=ins2.venv[ins2.vloops][0];
- env[0].sloope=ins2.venv[ins2.vloope][0];
- }
- }
- if (ins2.vtype&4)
- {
- if ((ins2.vtype&2)&&(ins2.vsustain==ins2.vloope))
- {
- env[0].type|=mpEnvSLoop;
- env[0].sloops=ins2.venv[ins2.vloops][0];
- env[0].sloope=ins2.venv[ins2.vloope][0];
- }
- else
- {
- env[0].type|=mpEnvLoop;
- env[0].loops=ins2.venv[ins2.vloops][0];
- env[0].loope=ins2.venv[ins2.vloope][0];
- }
- }
- }
- if (ins2.ptype&1)
- {
- env[1].speed=0;
- env[1].type=0;
- env[1].env=new unsigned char[ins2.penv[ins2.pnum-1][0]+1];
- if (!env[1].env)
- return errAllocMem;
- short k, p=0, h=ins2.penv[0][1]*4;
- for (j=1; j<ins2.pnum; j++)
- {
- short l=ins2.penv[j][0]-p;
- short dh=ins2.penv[j][1]*4-h;
- for (k=0; k<l; k++)
- {
- short cv=h+dh*k/l;
- env[1].env[p++]=(cv>255)?255:cv;
- }
- h+=dh;
- }
- env[1].len=p;
- env[1].env[p]=(h>255)?255:h;
- if (ins2.ptype&2)
- {
- env[1].type|=mpEnvSLoop;
- if (!(ins2.ptype&4)||(ins2.psustain<=ins2.ploope))
- {
- env[1].sloops=ins2.penv[ins2.psustain][0];
- env[1].sloope=ins2.penv[ins2.psustain][0]+1;
- }
- else
- {
- env[1].sloops=ins2.penv[ins2.ploops][0];
- env[1].sloope=ins2.penv[ins2.ploope][0];
- }
- }
- if (ins2.ptype&4)
- {
- if ((ins2.ptype&2)&&(ins2.psustain==ins2.ploope))
- {
- env[1].type|=mpEnvSLoop;
- env[1].sloops=ins2.penv[ins2.ploops][0];
- env[1].sloope=ins2.penv[ins2.ploope][0];
- }
- else
- {
- env[1].type|=mpEnvLoop;
- env[1].loops=ins2.penv[ins2.ploops][0];
- env[1].loope=ins2.penv[ins2.ploope][0];
- }
- }
- }
- for (j=0; j<ins1.samp; j++)
- {
- struct
- {
- unsigned long samplen;
- unsigned long loopstart;
- unsigned long looplen;
- unsigned char vol;
- signed char finetune;
- unsigned char type;
- unsigned char pan;
- signed char relnote;
- unsigned char res;
- unsigned char name[22];
- } samp;
- file.read(&samp, sizeof (samp));
- file.seekcur(ins2.shsize-sizeof(samp));
- if (samp.type&16)
- {
- samp.samplen>>=1;
- samp.loopstart>>=1;
- samp.looplen>>=1;
- }
-
- sample &sp=msmps[i][j];
- memcpy(sp.name, samp.name, 22);
- sp.name[22]=0;
- sp.handle=0xFFFF;
- sp.normnote=-samp.relnote*256-samp.finetune*2;
- sp.stdvol=(samp.vol>0x3F)?0xFF:(samp.vol<<2);
- sp.stdpan=samp.pan;
- sp.opt=0;
- sp.volfade=volfade;
- sp.vibtype=ins2.vibtype;
- sp.vibdepth=ins2.vibdepth<<2;
- sp.vibspeed=0;
- sp.vibrate=ins2.vibrate<<8;
- sp.vibsweep=0xFFFF/(ins2.vibsweep+1);
- sp.volenv=env[0].env?(2*i+0):0xFFFF;
- sp.panenv=env[1].env?(2*i+1):0xFFFF;
- sp.pchenv=0xFFFF;
-
- sampleinfo &sip=smps[i][j];
- sip.length=samp.samplen;
- sip.loopstart=samp.loopstart;
- sip.loopend=samp.loopstart+samp.looplen;
- sip.samprate=8363;
- sip.type=mcpSampDelta|((samp.type&16)?mcpSamp16Bit:0)|((samp.type&3)?(((samp.type&3)==2)?(mcpSampLoop|mcpSampBiDi):mcpSampLoop):0);
- }
- for (j=0; j<ins1.samp; j++)
- {
- sample &sp=msmps[i][j];
- sampleinfo &sip=smps[i][j];
- unsigned long l=sip.length<<(!!(sip.type&mcpSamp16Bit));
- if (!l)
- continue;
- sip.ptr=new char [l+16];
- if (!sip.ptr)
- return errAllocMem;
- file.read(sip.ptr, l);
- sp.handle=m.nsampi++;
- }
- m.nsamp+=ins1.samp;
- }
-
- m.samples=new sample [m.nsamp];
- m.sampleinfos=new sampleinfo [m.nsampi];
- if (!m.samples||!m.sampleinfos)
- return errAllocMem;
-
- m.nsampi=0;
- m.nsamp=0;
- for (i=0; i<m.ninst; i++)
- {
- for (j=0; j<instsmpnum[i]; j++)
- {
- m.samples[m.nsamp++]=msmps[i][j];
- if (smps[i][j].ptr)
- m.sampleinfos[m.nsampi++]=smps[i][j];
- }
- delete smps[i];
- delete msmps[i];
- }
- delete smps;
- delete msmps;
- delete instsmpnum;
-
- return errOk;
- }
-
- void xmpFreeModule(xmodule &m)
- {
- int i;
- if (m.sampleinfos)
- for (i=0; i<m.nsampi; i++)
- delete m.sampleinfos[i].ptr;
- delete m.sampleinfos;
- delete m.samples;
- if (m.envelopes)
- for (i=0; i<m.nenv; i++)
- delete m.envelopes[i].env;
- delete m.envelopes;
- delete m.instruments;
- if (m.patterns)
- for (i=0; i<m.npat; i++)
- delete m.patterns[i];
- delete m.patterns;
- delete m.patlens;
- delete m.orders;
- }
-
-
-
- static unsigned short modnotetab[85]=
- {
- 0xCFF, 0xC44, 0xB94, 0xAED, 0xA50, 0x9BC, 0x930, 0x8AC, 0x830, 0x7BA, 0x74B, 0x6E2,
- 0x67F, 0x622, 0x5CA, 0x577, 0x528, 0x4DE, 0x498, 0x456, 0x418, 0x3DD, 0x3A5, 0x371,
- 0x340, 0x311, 0x2E5, 0x2BB, 0x294, 0x26F, 0x24C, 0x22B, 0x20C, 0x1EE, 0x1D3, 0x1B9,
- 0x1A0, 0x188, 0x172, 0x15E, 0x14A, 0x138, 0x126, 0x116, 0x106, 0x0F7, 0x0E9, 0x0DC,
- 0x0D0, 0x0C4, 0x0B9, 0x0AF, 0x0A5, 0x09C, 0x093, 0x08B, 0x083, 0x07C, 0x075, 0x06E,
- 0x068, 0x062, 0x05D, 0x057, 0x053, 0x04E, 0x04A, 0x045, 0x041, 0x03E, 0x03A, 0x037,
- 0x034, 0x031, 0x02E, 0x02C, 0x029, 0x027, 0x025, 0x023, 0x021, 0x01F, 0x01D, 0x01C, 0
- };
-
- static inline unsigned long swapb2(unsigned short a)
- {
- return ((a&0xFF)<<9)|((a&0xFF00)>>7);
- }
-
- static int loadmod(xmodule &m, binfile &file, int chan, int sig)
- {
- m.envelopes=0;
- m.samples=0;
- m.instruments=0;
- m.sampleinfos=0;
- m.patlens=0;
- m.patterns=0;
- m.orders=0;
- m.nenv=0;
- m.linearfreq=0;
-
- unsigned long l=file[1080].getl();
-
- m.ninst=31;
- m.nchan=0;
-
- switch (l)
- {
- case 0x2E4B2E4D: // M.K.
- case 0x214B214D: // M!K!
- case 0x34544C46: // FLT4
- m.nchan=4;
- break;
- case 0x2E542E4E: // N.T.
- m.nchan=4;
- m.ninst=15;
- break;
- case 0x31384443: m.nchan=8; break; // CD81
-
- case 0x315A4454: m.nchan=1; break; // TDZ1
- case 0x325A4454: m.nchan=2; break;
- case 0x335A4454: m.nchan=3; break;
- case 0x345A4454: m.nchan=4; break;
- case 0x355A4454: m.nchan=5; break;
- case 0x365A4454: m.nchan=6; break;
- case 0x375A4454: m.nchan=7; break;
- case 0x385A4454: m.nchan=8; break;
- case 0x395A4454: m.nchan=9; break;
-
- case 0x4E484331: m.nchan=1; break; // 1CHN...
- case 0x4E484332: m.nchan=2; break;
- case 0x4E484333: m.nchan=3; break;
- case 0x4E484334: m.nchan=4; break;
- case 0x4E484335: m.nchan=5; break;
- case 0x4E484336: m.nchan=6; break;
- case 0x4E484337: m.nchan=7; break;
- case 0x4E484338: m.nchan=8; break;
- case 0x4E484339: m.nchan=9; break;
- case 0x48433031: m.nchan=10; break; // 10CH...
- case 0x48433131: m.nchan=11; break;
- case 0x48433231: m.nchan=12; break;
- case 0x48433331: m.nchan=13; break;
- case 0x48433431: m.nchan=14; break;
- case 0x48433531: m.nchan=15; break;
- case 0x48433631: m.nchan=16; break;
- case 0x48433731: m.nchan=17; break;
- case 0x48433831: m.nchan=18; break;
- case 0x48433931: m.nchan=19; break;
- case 0x48433032: m.nchan=20; break;
- case 0x48433132: m.nchan=21; break;
- case 0x48433232: m.nchan=22; break;
- case 0x48433332: m.nchan=23; break;
- case 0x48433432: m.nchan=24; break;
- case 0x48433532: m.nchan=25; break;
- case 0x48433632: m.nchan=26; break;
- case 0x48433732: m.nchan=27; break;
- case 0x48433832: m.nchan=28; break;
- case 0x48433932: m.nchan=29; break;
- case 0x48433033: m.nchan=30; break;
- case 0x48433133: m.nchan=31; break;
- case 0x48433233: m.nchan=32; break;
- case 0x38544C46: // FLT8
- return errFormSupp;
- m.nchan=8;
- break;
- default:
- if (sig==1)
- return errFormSig;
- m.ninst=(sig==2)?31:15;
- break;
- }
-
- if (chan)
- m.nchan=chan;
-
- if (!m.nchan)
- return errFormSig;
-
- m.nsampi=m.ninst;
- m.nsamp=m.ninst;
- m.instruments=new instrument[m.ninst];
- m.samples=new sample[m.ninst];
- m.sampleinfos=new sampleinfo[m.ninst];
- if (!m.instruments||!m.samples||!m.sampleinfos)
- return errAllocMem;
- memset(m.samples, 0, sizeof(*m.samples)*m.ninst);
- memset(m.sampleinfos, 0, sizeof(*m.sampleinfos)*m.ninst);
-
- file[0].read(m.name, 20);
- m.name[20]=0;
-
- int i;
-
- for (i=0; i<m.ninst; i++)
- {
- struct
- {
- char name[22];
- unsigned short length;
- signed char finetune;
- unsigned char volume;
- unsigned short loopstart;
- unsigned short looplength;
- } mi;
- file.read(&mi, sizeof(mi));
- unsigned long length=swapb2(mi.length);
- unsigned long loopstart=swapb2(mi.loopstart);
- unsigned long looplength=swapb2(mi.looplength);
- if (length<4)
- length=0;
- if (looplength<4)
- looplength=0;
- if (!looplength||(loopstart>=length))
- looplength=0;
- else
- if ((loopstart+looplength)>length)
- looplength=length-loopstart;
- if (mi.finetune&0x08)
- mi.finetune|=0xF0;
-
- instrument &ip=m.instruments[i];
- sample &sp=m.samples[i];
- sampleinfo &sip=m.sampleinfos[i];
-
- memcpy(ip.name, mi.name, 22);
- int j;
- for (j=21; j>=0; j--)
- if (ip.name[j]>=0x20)
- break;
- ip.name[j+1]=0;
- memset(ip.samples, -1, 256);
- *sp.name=0;
- sp.handle=0xFFFF;
- sp.stdpan=-1;
- sp.opt=0;
- sp.normnote=-mi.finetune*32;
- sp.stdvol=(mi.volume>0x3F)?0xFF:(mi.volume<<2);
- sp.volenv=0xFFFF;
- sp.panenv=0xFFFF;
- sp.pchenv=0xFFFF;
- sp.volfade=0;
- sp.vibspeed=0;
- sp.vibrate=0;
- if (!length)
- continue;
- for (j=0; j<128; j++)
- ip.samples[j]=i;
- sp.handle=i;
-
- sip.length=length;
- sip.loopstart=loopstart;
- sip.loopend=loopstart+looplength;
- sip.samprate=8363;
- sip.type=looplength?mcpSampLoop:0;
- }
-
- unsigned char orders[128];
- unsigned char ordn=file.getc();
- unsigned char loopp=file.getc();
-
- file.read(orders, 128);
- if (loopp>=ordn)
- loopp=0;
- short pn=0;
- short t;
- for (t=0; t<128; t++)
- if (pn<orders[t])
- pn=orders[t];
- pn++;
-
- m.nord=ordn;
- m.loopord=loopp;
-
- m.npat=pn;
-
- m.initempo=6;
- m.inibpm=125;
-
- if (sig)
- file.getl();
-
- m.orders=new unsigned short [m.nord];
- m.patlens=new unsigned short [m.npat];
- m.patterns=(unsigned char (**)[5])new void *[m.npat];
- unsigned char *temppat=new unsigned char [4*64*m.nchan];
- if (!m.orders||!m.patlens||!m.patterns||!temppat)
- return errAllocMem;
-
- for (i=0; i<m.nord; i++)
- m.orders[i]=orders[i];
-
- memset(m.patterns, 0, sizeof(*m.patterns)*m.npat);
-
- for (i=0; i<m.npat; i++)
- {
- m.patlens[i]=64;
- m.patterns[i]=new unsigned char [64*m.nchan][5];
- if (!m.patterns[i])
- return errAllocMem;
- }
-
- for (i=0; i<pn; i++)
- {
- unsigned char *dp=(unsigned char *)(m.patterns[i]);
- unsigned char *sp=temppat;
- file.read(temppat, 256*m.nchan);
- int j;
- for (j=0; j<(64*m.nchan); j++)
- {
- unsigned short nvalue=((short)(sp[0]&0xF)<<8)+sp[1];
- dp[0]=0;
- if (nvalue)
- {
- int k;
- for (k=0; k<85; k++)
- if (modnotetab[k]<=nvalue)
- break;
- dp[0]=k+13;
- }
- dp[1]=(sp[2]>>4)|(sp[0]&0x10);
- dp[2]=0;
- dp[3]=sp[2]&0xF;
- dp[4]=sp[3];
-
- if (dp[3]==0xE)
- {
- dp[3]=36+(dp[4]>>4);
- dp[4]&=0xF;
- }
- if (!dp[4])
- switch (dp[3])
- {
- case 10: case 46: case 47:
- dp[3]=0;
- }
-
- sp+=4;
- dp+=5;
- }
- }
- delete temppat;
-
- for (i=0; i<m.ninst; i++)
- {
- instrument &ip=m.instruments[i];
- sample &sp=m.samples[i];
- sampleinfo &sip=m.sampleinfos[i];
- if (sp.handle==0xFFFF)
- continue;
- sip.ptr=new unsigned char[sip.length+8];
- if (!sip.ptr)
- return errAllocMem;
- memset(sip.ptr, 0, sip.length);
- file.read(sip.ptr, sip.length);
- sp.handle=i;
- }
-
- return errOk;
- }
-
- int xmpLoadMOD(xmodule &m, binfile &file)
- {
- return loadmod(m, file, 0, 1);
- }
-
- int xmpLoadM31(xmodule &m, binfile &file)
- {
- return loadmod(m, file, 4, 2);
- }
-
- int xmpLoadM15(xmodule &m, binfile &file)
- {
- return loadmod(m, file, 4, 0);
- }
-
- int xmpLoadWOW(xmodule &m, binfile &file)
- {
- return loadmod(m, file, 8, 1);
- }
-